libxenlight: clean up the domain when it dies
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 25 Nov 2009 14:19:20 +0000 (14:19 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 25 Nov 2009 14:19:20 +0000 (14:19 +0000)
This patch adds two functions to libxenlight to be able to recognize
when a particular domain dies. After creating a domain, xl uses these
functions to wait for its death and clean up its resources.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
tools/libxl/libxl.c
tools/libxl/libxl.h
tools/libxl/xl.c

index 47fe8e1ea6fdb73e2436f842d88904446b73a5b5..da2d1dfce1d71af8e610d0000c92216584c338ed 100644 (file)
@@ -54,9 +54,18 @@ int libxl_ctx_free(struct libxl_ctx *ctx)
 {
     libxl_free_all(ctx);
     free(ctx->alloc_ptrs);
-    ctx->alloc_ptrs = NULL;
+    ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
+    if (!ctx->alloc_ptrs)
+        return ERROR_NOMEM;
+    return 0;
+}
+
+int libxl_ctx_close(struct libxl_ctx *ctx)
+{
+    libxl_ctx_free(ctx);
+    free(ctx->alloc_ptrs);
     xc_interface_close(ctx->xch);
-    xs_daemon_close(ctx->xsh);
+    xs_daemon_close(ctx->xsh); 
     return 0;
 }
 
@@ -352,6 +361,46 @@ int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req)
     return 0;
 }
 
+int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd)
+{
+    if (!xs_watch(ctx->xsh, "@releaseDomain", "domain_death"))
+        return -1;
+    *fd = xs_fileno(ctx->xsh);
+    return 0;
+}
+
+int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t *info)
+{
+    unsigned int num;
+    int nb_domain, i, rc = 0;
+    char **vec = NULL;
+    xc_dominfo_t *list = NULL;
+
+    vec = xs_read_watch(ctx->xsh, &num);
+    if (!vec)
+        return 0;
+    if (!strcmp(vec[XS_WATCH_TOKEN], "domain_death")) {
+        list = libxl_domain_infolist(ctx, &nb_domain);
+        for (i = 0; i < nb_domain; i++) {
+            if (domid == list[i].domid) {
+                if (list[i].running || (!list[i].shutdown && !list[i].crashed && !list[i].dying))
+                    goto out;
+                *info = list[i];
+                rc = 1;
+                goto out;
+            }
+        }
+        memset(info, 0x00, sizeof(xc_dominfo_t));
+        rc = 1;
+        goto out;
+    }
+
+out:
+    free(list);
+    free(vec);
+    return rc;
+}
+
 static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
 {
     char *pid;
@@ -409,11 +458,6 @@ int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
     }
     if (libxl_destroy_device_model(ctx, domid) < 0)
         XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid);
-    rc = xc_domain_destroy(ctx->xch, domid);
-    if (rc < 0) {
-        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
-        return -1;
-    }
     if (libxl_devices_destroy(ctx, domid, force) < 0)
         XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
     if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
@@ -421,6 +465,11 @@ int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
     snprintf(vm_path, sizeof(vm_path), "/vm/%s", libxl_uuid_to_string(ctx, uuid));
     if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path);
+    rc = xc_domain_destroy(ctx->xch, domid);
+    if (rc < 0) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
+        return -1;
+    }
     return 0;
 }
 
index 890f5c8c49a25da0d22fb970aff17c72a60503aa..b568bc48631a3dc78f4f7f2351a827c321e3a15c 100644 (file)
@@ -227,6 +227,7 @@ typedef struct  {
 /* context functions */
 int libxl_ctx_init(struct libxl_ctx *ctx);
 int libxl_ctx_free(struct libxl_ctx *ctx);
+int libxl_ctx_close(struct libxl_ctx *ctx);
 int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, void *log_data);
 
 /* domain related functions */
@@ -239,6 +240,9 @@ int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info,
 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
 int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
 
+int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd);
+int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t *info);
+
 int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid);
 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid);
 
index c984f156f4e33fb9e49d182b3c280061c4fe765e..4c746609518815e31cd826fdaa386617dd5f6456 100644 (file)
 #include <sys/time.h> /* for time */
 #include <getopt.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/socket.h>
+#include <sys/select.h>
 #include <arpa/inet.h>
 #include <xenctrl.h>
 
@@ -584,7 +587,8 @@ static void create_domain(int debug, const char *filename)
     libxl_device_vkb *vkbs = NULL;
     libxl_device_console console;
     int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
-    int i;
+    int i, fd;
+    int need_daemon = 1;
     libxl_device_model_starting *dm_starting = 0;
 
     printf("Parsing config file %s\n", filename);
@@ -592,6 +596,9 @@ static void create_domain(int debug, const char *filename)
     if (debug)
         printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
 
+start:
+    domid = 0;
+
     libxl_ctx_init(&ctx);
     libxl_ctx_set_log(&ctx, log_callback, NULL);
     libxl_domain_make(&ctx, &info1, &domid);
@@ -632,6 +639,36 @@ static void create_domain(int debug, const char *filename)
 
     libxl_domain_unpause(&ctx, domid);
 
+    if (need_daemon) {
+        daemon(0, 0);
+        need_daemon = 0;
+    }
+    
+    libxl_wait_for_domain_death(&ctx, domid, &fd);
+    while (1) {
+        int ret;
+        fd_set rfds;
+        xc_dominfo_t info;
+        memset(&info, 0x00, sizeof(xc_dominfo_t));
+
+        FD_ZERO(&rfds);
+        FD_SET(fd, &rfds);
+
+        ret = select(fd + 1, &rfds, NULL, NULL, NULL);
+        if (!ret)
+            continue;
+        if (libxl_is_domain_dead(&ctx, domid, &info)) {
+            if (info.crashed || info.dying || (info.shutdown && (info.shutdown_reason != SHUTDOWN_suspend))) {
+                libxl_domain_destroy(&ctx, domid, 0);
+                if (info.shutdown && (info.shutdown_reason == SHUTDOWN_reboot)) {
+                    libxl_ctx_free(&ctx);
+                    goto start;
+                }
+            }
+            exit(0);
+        }
+    }
+
     for (i = 0; i < num_vifs; i++) {
         free(vifs[i].smac);
         free(vifs[i].ifname);